#include "Program.h"

    /*********************************************/
    /*              Constructor                  */
    /*********************************************/

        GLSLProgram::GLSLProgram(std::string name, Shader * shader1, Shader * shader2 )
        {
            m_Name = name;

            m_Shaders.push_back(shader1);
            m_Shaders.push_back(shader2);

            Init();
        }

        GLSLProgram::~GLSLProgram()
        {
            for(int i=0;i< m_Shaders.size();i++)
            {
                delete [] m_Shaders[i];
            }

            glDeleteProgram(m_GLID);   // Destroy the program
        }

    /*********************************************/
    /*              Members                      */
    /*********************************************/
		
		/*********************************************/
		/*              Methods                      */
		/*********************************************/

            int GLSLProgram::Init()
            {
                CreateProgram();    // Create the program from stored shaders
                LinkProgram();      // Link the program

                return true;
            }

            int GLSLProgram::CreateProgram()
            {
                m_GLID = glCreateProgram();              //   Creation Program

                for(int i=0;i< m_Shaders.size();    i++)
                {
                    glAttachShader(m_GLID, m_Shaders[i]->m_Id);
                }

                return 1;
            }

            int GLSLProgram::LinkProgram()
            {
                try
                {
                    glLinkProgram(m_GLID);           // Linkage du program
                    SetAttributes();

                    GLint link(0);
                    glGetProgramiv(m_GLID, GL_LINK_STATUS, &link);

                    if(link != GL_TRUE) throw (0);      // Did the link worked?

                    return 1;       // If everything worked as planned, return true
                }
                catch (int i)
                {
                    if(i==0)
                    {
                        // Here we get back the length of the error alert

                        GLint tailleErreur(0);
                        char *erreur(NULL);

                        glGetProgramiv(m_GLID, GL_INFO_LOG_LENGTH, &tailleErreur);

                        // Allocation de l'erreur

                        erreur = new char[tailleErreur + 1];

                        // Copie de l'erreur dans la chaine de caractères

                        glGetProgramInfoLog(m_GLID, tailleErreur, &tailleErreur, erreur);

                        erreur[tailleErreur] = '\0';


                        // Affichage de l'erreur

                        std::cout << "Erreur lors du link du program : " << erreur << std::endl;

                        // On retourne false

                        delete[] erreur;
                        return false;
                    }
                }
            }

            void GLSLProgram::SetAttributes()
            {
                Attributes::m_Index.clear();


                Attributes::m_Index.push_back(glGetAttribLocation(m_GLID,"a_Position"));
                Attributes::m_Index.push_back(glGetAttribLocation(m_GLID,"a_Color"));
                Attributes::m_Index.push_back(glGetAttribLocation(m_GLID,"a_Normal"));
                Attributes::m_Index.push_back(glGetAttribLocation(m_GLID,"a_TexCoord0"));



                /*
                GLchar * info = new GLchar[200];
                int length;
                GLint size;
                GLenum type;

                glGetActiveAttrib(
                                        m_Program,
                                        0,
                                        200,
                                        &length,
                                        &size,
                                        &type,
                                        info
                                    );

                */
              //  glBindAttribLocation(m_Program, 0, "a_Position");

               // printf(" Attribute info : \n %s \n", info);

              /*  Attributes::m_Index.push_back(0);
                Attributes::m_Index.push_back(1);
                Attributes::m_Index.push_back(2);
                Attributes::m_Index.push_back(3);

        */

               /*
                    glBindAttribLocation(m_Program, 0, "a_Position");
                    glBindAttribLocation(m_Program, 1, "a_Color");
                    glBindAttribLocation(m_Program, 2, "a_Normal");
                    glBindAttribLocation(m_Program, 3, "a_TexCoord0");
                */
            }

            void GLSLProgram::Use()
            {
                glUseProgram(m_GLID);
            }

            void GLSLProgram::DisableProgram()
            {
                glUseProgram(0);
            }
	
    /*********************************************/
    /*              Static                       */
    /*********************************************/
		
		/*********************************************/
        /*              Properties                   */
		/*********************************************/

            std::vector<GLSLProgram *>  GLSLProgram::Programs;

        /*********************************************/
        /*              Methods                      */
        /*********************************************/

            GLuint	GLSLProgram::New(std::string name, Shader * shader1, Shader * shader2 )
			{
                GLSLProgram * program = new GLSLProgram(name, shader1, shader2);
                Programs.push_back(program);

                return (program->m_GLID);
			}

			GLuint GLSLProgram::Find(std::string name)
			{
				for(int i=0; i< Programs.size(); i++)
                {
                    printf("ProgramFind  %s \n", name.c_str());
                    if(Programs[i]->m_Name==name)
					{
                        printf("ProgramFind \n");
                        return Programs[i]->m_GLID;
					}
				}
				return -1;
			}
			
            void GLSLProgram::Use(GLuint GLID)
			{
				glUseProgram(GLID);
			}
			
			void GLSLProgram::Disable()
			{
				glUseProgram(0);
			}
